﻿Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.IO
Imports System.IO.Compression

<ToolboxBitmap(GetType(SAUpdaterCheck), "Icon_16_SA_UP_CHCK.png")>
Public Class SAUpdaterCheck
    Private mRepositoryDefinition As String
    Private mServer As String
    Private mFolder As String
    Private mVersionFile As String

    Private mAuto As Boolean
    Private mCheckInterval As Integer
    Private mError As New SAEventArgs("", SAEventArgs.Results.Success)
    Private mHandlerAdded As Boolean = False
    Private mNewType As String

    Private mManualChecked As Boolean
    Private gTimer As New System.Timers.Timer

#Region "Public Events"
    Public Event UpdateChecked(Result As SAEventArgs)
    Public Event InstallerDownloadProgress(PercentageCompleted As Integer)
    Public Event InstallerDownloadCompleted(Success As Boolean)
    Public Event HelpDownloadProgress(PercentageCompleted As Integer)
    Public Event HelpDownloadCompleted(Success As Boolean)
#End Region
#Region "Private Events"
    Private Event CheckForUpdate()
#End Region
#Region "Get/Set Properties"
    <Category("Repository")>
    <Description("Used to load a definition file created by SAUpdater to specify the various repository attributes.")>
    <Editor(GetType(UIFileEditor), GetType(UITypeEditor))>
    Public Property RepositoryDefinition As String
        Get
            Return mRepositoryDefinition
        End Get
        Set(value As String)
            Dim tString As String
            If value Is Nothing Then
                tString = ""
            Else
                tString = value
            End If

            If tString.Trim = "" Then
                RepositoryServer = ""
                RepositoryFolder = ""
                VersionFile = ""
                mRepositoryDefinition = ""
            ElseIf tString.Trim <> "" And Me.DesignMode = True Then
                RepositoryServer = UpdateCore.RepositoryServer
                RepositoryFolder = UpdateCore.RepositoryFolder
                VersionFile = UpdateCore.VersionFile
                mRepositoryDefinition = value
            Else
                mRepositoryDefinition = value
            End If
        End Set
    End Property
    <Category("Repository")>
    <Description("Sets the value of the repository server. eg http://www.contoso.com")>
    Public Property RepositoryServer As String
        Get
            Return UpdateCore.RepositoryServer
        End Get
        Set(value As String)
            Dim tString As String
            If value Is Nothing Then
                tString = ""
            Else
                tString = value
            End If

            mServer = tString
            UpdateCore.RepositoryServer = mServer
            If mServer.Trim <> "" Then SetDefaults()
        End Set
    End Property
    <Category("Repository")>
    <Description("Sets the folder to be used on the repository server., eg /mySoftware/myApp")>
    Public Property RepositoryFolder As String
        Get
            Return UpdateCore.RepositoryFolder
        End Get
        Set(value As String)
            Dim tString As String
            If value Is Nothing Then
                tString = ""
            Else
                tString = value
            End If

            mFolder = tString
            UpdateCore.RepositoryFolder = mFolder
            If mFolder.Trim <> "" Then SetDefaults()
        End Set
    End Property
    <Category("Repository")>
   <Description("Sets the name for the Version file., eg Update.html")>
    Public Property VersionFile As String
        Get
            Return UpdateCore.VersionFile
        End Get
        Set(value As String)
            Dim tString As String
            If value Is Nothing Then
                tString = ""
            Else
                tString = value
            End If

            mVersionFile = tString
            UpdateCore.VersionFile = mVersionFile
            If mVersionFile.Trim <> "" Then SetDefaults()
        End Set
    End Property
    <Category("Update")>
    <Description("Set to True for Auto Version checking at the interval rate.")>
    Public Property AutoCheck As Boolean
        Get
            Return mAuto
        End Get
        Set(value As Boolean)
            mAuto = value
            If mAuto = True Then
                gTimer.Start()
            Else
                gTimer.Stop()
            End If
        End Set
    End Property
    <Category("Update")>
    <Description("Set the Check Internal in minutes. Minimum is 5 minutes.")>
    Public Property CheckInterval As Integer
        Get
            Return mCheckInterval
        End Get
        Set(value As Integer)
            mCheckInterval = value
            If mCheckInterval < 5 Then mCheckInterval = 5
        End Set
    End Property
    '<Category("Update")>
    '<Description("Set the Installation folder.")>
    'Public Property InstallerFolder As String
    '    Get
    '        Return mInstallerFolder
    '    End Get
    '    Set(value As String)
    '        mInstallerFolder = value
    '    End Set
    'End Property
    <Category("Version")>
    <Description("Set the current applivcation version. Format 0.0.0.0")>
    Public Property CurrentApplicationVersion As String
        Get
            Return UpdateCore.CurrentAppVersion
        End Get
        Set(value As String)
            Dim tString As String
            If value Is Nothing Then
                tString = "0.0.0.0"
            Else
                If value.Trim = "" Then
                    tString = "0.0.0.0"
                Else
                    tString = value
                End If
            End If
            UpdateCore.CurrentAppVersion = tString
        End Set
    End Property
    <Category("Version")>
    <Description("Set the current installer version. Format 0.0.0.0")>
    Public Property CurrentInstallerVersion As String
        Get
            Return UpdateCore.CurrentInstallerVersion
        End Get
        Set(value As String)
            Dim tString As String
            If value Is Nothing Then
                tString = "0.0.0.0"
            Else
                If value.Trim = "" Then
                    tString = "0.0.0.0"
                Else
                    tString = value
                End If
            End If
            UpdateCore.CurrentInstallerVersion = tString
        End Set
    End Property
    <Category("Version")>
    <Description("Set the current help file version. Format 0.0.0.0")>
    Public Property CurrentHelpVersion As String
        Get
            Return UpdateCore.CurrentHelpVersion
        End Get
        Set(value As String)
            Dim tString As String
            If value Is Nothing Then
                tString = "0.0.0.0"
            Else
                If value.Trim = "" Then
                    tString = "0.0.0.0"
                Else
                    tString = value
                End If
            End If
            UpdateCore.CurrentHelpVersion = tString
        End Set
    End Property
#Region "Non Browsable"
    <Description("Returns true if the check was successful, else false")>
    Public Function CheckUpdate() As Boolean
        mManualChecked = False
        RaiseEvent CheckForUpdate()
        Do
            Application.DoEvents()
        Loop Until mManualChecked = True
        If mError.Result <> SAEventArgs.Results.Success Then Return False
        Return True
    End Function
#End Region
#End Region
#Region "Get Properties"
#Region "VersionFile"
    <Browsable(False)>
    Public ReadOnly Property NewApplicationVersion As String
        Get
            Return gUpdateVersion.NewApplicationVersion
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property NewInstallerVersion As String
        Get
            Return gUpdateVersion.NewInstallerVersion
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property NewHelpVersion As String
        Get
            Return gUpdateVersion.NewHelpVersion
        End Get
    End Property
#End Region
    <Browsable(False)>
    Public Shared ReadOnly Property RepositoryMainUpdateFolder As String
        Get
            Return UpdateCore.FixURLText(UpdateCore.RepositoryServer & UpdateCore.RepositoryFolder)
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property RepositoryFileUpdateFolder As String
        Get
            Return UpdateCore.FixURLText(UpdateCore.FixURLText(UpdateCore.RepositoryServer & UpdateCore.RepositoryFolder) & "/UpdateFiles")
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property RepositoryFileDefinitionFile As String
        Get
            Dim tUFileList As String = "FileList_" & gUpdateVersion.NewApplicationVersion
            If gUpdateVersion.IsBeta = True Then tUFileList &= "_" & gUpdateVersion.NewType
            tUFileList = tUFileList & ".html"
            Return String.Format("{0}/{1}", UpdateCore.FixURLText(UpdateCore.RepositoryServer & UpdateCore.RepositoryFolder), tUFileList)
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property HasApplicationUpdate As Boolean
        Get
            Return gUpdateVersion.HasApplicationUpdate
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property IsDownloadCompulsory As Boolean
        Get
            Return gUpdateVersion.IsDownloadCompulsory
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property HasInstallerUpdate As Boolean
        Get
            Return gUpdateVersion.HasInstallerUpdate
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property HasHelpUpdate As Boolean
        Get
            Return gUpdateVersion.HasHelpUpdate
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property AllowUpdate As Boolean
        Get
            Return gUpdateVersion.AllowUpdate
        End Get
    End Property

    <Browsable(False)>
    Public ReadOnly Property IsBeta As Boolean
        Get
            Return gUpdateVersion.IsBeta
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property NewType As String
        Get
            Return gUpdateVersion.NewType
        End Get
    End Property
    <Browsable(False)>
    Public ReadOnly Property ErrorMessage As SAEventArgs
        Get
            Return mError
        End Get
    End Property
#End Region
    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        gUpdateVersion = New UpdateVersion
        AddHandler Me.CheckForUpdate, AddressOf ManualCheckUpdate

        If Me.DesignMode = True Then
            UpdateCore.Reset()
            If CheckInterval = 0 Then CheckInterval = 5
        End If
    End Sub
#Region "Check Update"
    Private Async Sub ManualCheckUpdate()
        If SetDefaults() = False Then Exit Sub

        Dim success As Boolean = Await gUpdateVersion.CheckUpdate()

        If success = True Then
            mError = New SAEventArgs("", SAEventArgs.Results.Success)

        Else
            mError = New SAEventArgs("Problem", SAEventArgs.Results.GeneralFailure)
        End If
        mManualChecked = True
    End Sub
    Private Async Sub TimeredCheckUpdate(sender As Object, e As EventArgs)
        If SetDefaults() = False Then Exit Sub

        Dim success As Boolean = Await gUpdateVersion.CheckUpdate()

        If success = True Then
            RaiseEvent UpdateChecked(New SAEventArgs("", SAEventArgs.Results.Success))
        Else
            RaiseEvent UpdateChecked(New SAEventArgs("Problem", SAEventArgs.Results.GeneralFailure))
        End If
    End Sub
    Private Function SetDefaults() As Boolean
        mNewType = ""

        If RepositoryServer Is Nothing Then RepositoryServer = ""
        If RepositoryFolder Is Nothing Then RepositoryFolder = ""
        If VersionFile Is Nothing Then VersionFile = ""

        UpdateCore.RepositoryServer = RepositoryServer
        UpdateCore.RepositoryFolder = RepositoryFolder
        UpdateCore.VersionFile = VersionFile

        If UpdateCore.RepositoryServer.Trim = "" Then
            SetErrorEncounteredState("Illegal Server Repository", SAEventArgs.Results.MissingServerName)
            Return False
        End If

        If UpdateCore.RepositoryFolder.Trim = "" Then
            SetErrorEncounteredState("Illegal Repository Folder", SAEventArgs.Results.MissingFolder)
            Return False
        End If

        If UpdateCore.VersionFile.Trim = "" Then
            SetErrorEncounteredState("Illegal Version File", SAEventArgs.Results.MissingVersionFile)
            Return False
        End If

        If CheckInterval = 0 Or CheckInterval = Nothing Then CheckInterval = 5
        gTimer.Interval = CheckInterval * 60000

        If mHandlerAdded = False Then
            AddHandler gTimer.Elapsed, AddressOf TimeredCheckUpdate
            mHandlerAdded = True
        End If
        Return True
    End Function
#End Region
#Region "Do Application Update"
    Public Function DoUpdate() As Boolean
        Dim tArguments As String

        'Check for Version update
        If UpdateCore.Connected(True) = True Then

            If UpdateCore.RepositoryServer.Trim = "" Then
                SetErrorEncounteredState("Illegal Server Repository", SAEventArgs.Results.MissingServerName)
                Return False
            End If

            If gUpdateVersion.InstallerFolder.Trim = "" Then
                SetErrorEncounteredState("Installer folder not defined", SAEventArgs.Results.MissingFolder)
                Return False
            ElseIf Directory.Exists(gUpdateVersion.InstallerFolder) = False Then
                SetErrorEncounteredState("Installer folder does not exists", SAEventArgs.Results.MissingFolder)
                Return False
            End If

            If File.Exists(gUpdateVersion.InstallerFile) = False Then
                SetErrorEncounteredState(gUpdateVersion.InstallerFile & " is missing", SAEventArgs.Results.FileMissing)
                Return False
            End If

            tArguments = "/V " & UpdateCore.CurrentAppVersion
            If mNewType = "" Then
                tArguments = "/UPDATE " & tArguments
            Else
                tArguments = String.Format("/UPDATE /BETA {0}", tArguments)
            End If

            Try
                Dim RunSvc As New ProcessStartInfo
                RunSvc.FileName = String.Format("""{0}""", gUpdateVersion.InstallerFile)
                RunSvc.Arguments = tArguments
                RunSvc.WindowStyle = ProcessWindowStyle.Normal
                RunSvc.UseShellExecute = False

                If Environment.OSVersion.Version.Major >= 6 Then RunSvc.Verb = "runas"
                Process.Start(RunSvc)
                SetErrorEncounteredState("", SAEventArgs.Results.Success)
                Return True
            Catch ex As Exception
                SetErrorEncounteredState("Error:" & ex.Message, SAEventArgs.Results.GeneralFailure)
                Return False
            End Try

        Else
            SetErrorEncounteredState("Not Connected to the internet", SAEventArgs.Results.NotConnected)
            Return False
        End If
    End Function
#End Region
#Region "Do Installer Update"
    Public Sub DoInstallerUpdate()
        Dim iu As New FileDownload
        AddHandler iu.PercentageChanged, AddressOf UpdateInstallerDownloadProgress
        AddHandler iu.DownLoadCompleted, AddressOf UpdateInstallerDownloadCompleted
        If Directory.Exists(gUpdateVersion.InstallerFolder) = False Then Directory.CreateDirectory(gUpdateVersion.InstallerFolder)
        iu.DownLoadFileToDestination(gUpdateVersion.RepositoryCompressedInstallerFile, gUpdateVersion.CompressedInstallerFile)
    End Sub
    Sub UpdateInstallerDownloadProgress(Percentage As Integer)
        RaiseEvent InstallerDownloadProgress(Percentage)
    End Sub
    Sub UpdateInstallerDownloadCompleted(Success As Boolean)
        Dim tSuccess As Boolean = Success
        If tSuccess = True Then
            Try
                If Security.GenerateFileMD5(gUpdateVersion.CompressedInstallerFile) = gUpdateVersion.NewInstallerMD5 Then
                    If File.Exists(gUpdateVersion.InstallerFile) = True Then File.Delete(gUpdateVersion.InstallerFile)
                    ZipFile.ExtractToDirectory(gUpdateVersion.CompressedInstallerFile, gUpdateVersion.InstallerFolder)
                Else
                    tSuccess = False
                End If
            Catch ex As Exception
            tSuccess = False
            mError = New SAEventArgs(ex.Message, SAEventArgs.Results.GeneralFailure)
        End Try
        End If
        RaiseEvent InstallerDownloadCompleted(tSuccess)
    End Sub
#End Region
#Region "Do Help Update"
    Public Sub DoHelpUpdate()
        Dim hu As New FileDownload
        AddHandler hu.PercentageChanged, AddressOf UpdateHelpDownloadProgress
        AddHandler hu.DownLoadCompleted, AddressOf UpdateHelpDownloadCompleted
    End Sub
    Sub UpdateHelpDownloadProgress(Percentage As Integer)
        RaiseEvent InstallerDownloadProgress(Percentage)
    End Sub
    Sub UpdateHelpDownloadCompleted(Success As Boolean)
        RaiseEvent InstallerDownloadCompleted(Success)
    End Sub
#End Region
    Private Sub SetErrorEncounteredState(Description As String, Result As SAEventArgs.Results)
        gTimer.Stop()
        mError = New SAEventArgs(Description, Result)
    End Sub
End Class
